/*
* 对工具类的封装包括
* 数组去重、        $app.distinct(ac)
* 数组下标的查找、   Array.findIndex()
* 数据类型判断、    $app.type(11)
* 时间戳转换、      $app.format_time_stamp('yyyy-MM-dd I',1524715465909)
* 小数点的处理、    $app.MathFormaFloat((0.1+0.2),3)
* 对象的判断        $app.contain(ab,'id',4)
*/
(function(window){

  var i = {
    // 数组以及数组对象去重
    distinct: function(arr,key){
      var a=[];
      if(arguments.length > 0 && isNaN(parseInt(arguments[1]))){
        for(var b=0;b<arr.length;b++){
          if(arguments.length==1?i.objArr(a,arguments[0][b])==-1:i.objArr(a,arguments[0][b].id,arguments[1])==-1){
            a.push(arr[b])
          }
        }
      }else{
        throw new TypeError('The parameter is incorrect. The first parameter must be an array. If it is the second parameter of the array object, it must be the key value key.');
      }
      return a
    },
    /*
    * @ 数组以及数组对象去重 array key
    */
    unique: function(){
      var hash=[],a=[];
      for (var i = 0; i < arguments[0].length; i++) {
          if( arguments.length > 1 && a.indexOf(arguments[0][i][arguments[1]])==-1 ){
            a.push(arguments[0][i][arguments[1]]);
            hash.push(arguments[0][i]);
          }else if( arguments.length == 1 && hash.indexOf(arguments[0][i])==-1 ){
            hash.push(arguments[0][i]);
          }
      }
      return hash;
    },
    /*
    * @数组排序或者对象key排序
    * @需要把arguments提出来在sort方法中arguments不想想要的参数
    */
    sort: function(){
      var argNum = arguments;
      if(argNum.length>0 && i.type(argNum[0],'array')){
        return argNum[0].sort(function(moduleA, moduleB){
          if(argNum[1] && isNaN(parseInt(argNum[1]))){
            if(moduleA[argNum[1]] < moduleB[argNum[1]]){
              return -1;
            }else{
              return 1;
            }
          }else{
            if(moduleA < moduleB){
              return -1;
            }else{
              return 1;
            }
          }
        })
      }else{
        throw new TypeError('The given parameter is not an array');
      }
    },
    // 查找指定元素的下标
    objArr: function(){
      var data = arguments;
      if(i.type(data[0],'array')){
        if(data.length>1 && data.length<4){
          return data[0].findIndex(function(e){
            return data.length==2?e==data[1]:e[data[2]]==data[1]
          })
        }else{
          throw new TypeError('The parameter is incorrect, the first is an array, and the second parameter is the key value pair of the object.');
        }
      }else{
        throw new TypeError('The given parameter is not an array');
      }
    },
    // 判断数据类型
    type: function(){
      if(arguments.length > 0){
        var a = Object.prototype.toString.call(arguments[0]);
        var newA = a.split(' ')[1].slice(0,-1).toLowerCase();
        switch (arguments.length){
          case 1:
            return newA;
          case 2:
            if(newA==arguments[1]){
              return true
            }else{
              return false
            }
          default:
     				return;
        }
      }else{
        throw new TypeError('The parameter is incorrect, the first parameter is the object to be judged, or the second parameter is the type.');
      }
  	},
    /*
    * 格式化时间戳
    * 在转换时间为时间戳时需要替换'-'为'/'否则得到的是一个NaN
    */
    format_time_stamp: function(format,timestamp){
    	var newDate = new Date();
      var timeType = timestamp;
      if(isNaN(timestamp)){
        timeType = new Date(timestamp.replace(/-/g,'/')).getTime();
      }
    	newDate.setTime(timeType);
    	return newDate.format(format);
    },
    // @计算的精确度封装api.MathFormaFloat(a,b) a值 b小数点
    MathFormaFloat: function(a,b){
      var c = Math.pow(10,b);
      return Math.round(a*c,10)/c;
    },
    // @判断数组中是否存在指定对象的值api.contain(a,b,c) a数组 b对象 c值
    contain: function (arr,obj,val) {
      var i = arr.length;
      while (i--) {
          if (arr[i][obj] == val) {
              return true;
          }
      }
      return false;
    },
    //两个字符串的相似程度，并返回相似度百分比
    strSimilarity2Percent: function (s, t) {
      var l = s.length > t.length ? s.length : t.length;
      var d = this.strSimilarity2Number(s, t);
      return (1 - d / l).toFixed(4);
    },
    strSimilarity2Number: function (s, t) {
       var n = s.length, m = t.length, d = [];
       var i, j, s_i, t_j, cost;
       if (n == 0) return m;
       if (m == 0) return n;
       for (i = 0; i <= n; i++) {
           d[i] = [];
           d[i][0] = i;
       }
       for (j = 0; j <= m; j++) {
           d[0][j] = j;
       }
       for (i = 1; i <= n; i++) {
           s_i = s.charAt(i - 1);
           for (j = 1; j <= m; j++) {
               t_j = t.charAt(j - 1);
               if (s_i == t_j) {
                   cost = 0;
               } else {
                   cost = 1;
               }
               d[i][j] = this.Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
           }
       }
       return d[n][m];
    },
    Minimum: function (a, b, c) {
      return a < b ? (a < c ? a : c) : (b < c ? b : c);
    },
    ///<summary>获得字符串实际长度，中文2，英文1</summary>
    ///<param name="str">要获得长度的字符串</param>
    GetLength: function (str) {
      if(typeof str !='string'){
        throw new TypeError('The parameter is incorrect, the first parameter is the string');
      }
      var realLength = 0, len = str.length, charCode = -1;
      for (var i = 0; i < len; i++) {
        charCode = str.charCodeAt(i);
        if (charCode >= 0 && charCode <= 128) realLength += 1;
        else realLength += 2;
      }
      return realLength;
    },
    regular: {
      email:{desc:"验证Email地址",rule:"/^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$/"},
      phone:{desc:"验证电话号码",rule:"/^1[3456789]\\d{9}$/"},
      card:{desc:"验证身份证号",rule:"/^\\d{15}|\\d{18}$/"},
    	number:{desc:"整数或者小数",rule:"/^[0-9]+\\.{0,1}[0-9]{0,2}$/"},
    	int:{desc:"只能输入数字",rule:"/^[0-9]*$/"},
    	name:{desc:"4~8位汉字、数字或字母",rule:"/[\u4e00-\u9fa5a-zA-Z0-9]{4,8}/"},
    	passW:{desc:"8~12位字母和数字",rule:"/(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]{8,12}/"}, // 需8-12位数字或字母组成
    	social:{desc:"18位字母和数字",rule:"/[1-9A-GY]{1}[1239]{1}[1-5]{1}[0-9]{5}[0-9A-Z]{10}/"},
      urlJSON:{desc:"https|ftp|file匹配链接",rule:"/(https?|ftp|file):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/"}
    	///^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/
    },
    test: function(name,value){ // 正则匹配true false
    	return reg.test(value);
    },
    match: function(reg,val){  // 正则匹配返回数组
      return val.match(regular[reg])
    },
    remSpace: function(){ // 删除空格
      return arguments[0].replace(/\s+/g,'')
    }
  }

  //扩展日期格式化属性
  if(!Date.prototype.format){
    Date.prototype.format = function(fmt){ //author: meizz
      var o = {
        "M+" : this.getMonth()+1,                 //月份
        "d+" : this.getDate(),                    //日
        "h+" : this.getHours(),                   //小时
        "m+" : this.getMinutes(),                 //分
        "s+" : this.getSeconds(),                 //秒
        "q+" : Math.floor((this.getMonth()+3)/3), //季度
        "S"  : this.getMilliseconds(),            //毫秒
        "I"  : function(){                        //时段
          var a = this.getHours();
          if(5<=a && a<7)return '清晨';
          if(7<=a && a<9)return '早上';
          if(9<=a && a<12)return '上午';
          if(12<=a && a<14)return '中午';
          if(14<=a && a<18)return '下午';
          if(18<=a && a<19)return '傍晚';
          if(19<=a && a<24)return '晚上';
          if(24<=a && a<5)return '凌晨';
        }.bind(this)
      };
      if(/(y+)/.test(fmt))
        fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
      for(var k in o)
        if(new RegExp("("+ k +")").test(fmt))
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
      return fmt;
    }
  }

  //扩展数组findIndex属性
  if (!Array.prototype.findIndex) {
    Object.defineProperty(Array.prototype, 'findIndex', {
      value: function(predicate) {
        if (this == null) {
          throw new TypeError('"this" is null or not defined');
        }
        var o = Object(this);
        var len = o.length >>> 0;
        if (typeof predicate !== 'function') {
          throw new TypeError('predicate must be a function');
        }
        var thisArg = arguments[1];
        var k = 0;
        while (k < len) {
          var kValue = o[k];
          if (predicate.call(thisArg, kValue, k, o)) {
            return k;
          }
          k++;
        }
        return -1;
      }
    });
  }

  //扩展数组find属性
  if (!Array.prototype.find) {
    Object.defineProperty(Array.prototype, 'find', {
      value: function(predicate) {
        if (this == null) {
          throw new TypeError('"this" is null or not defined');
        }
        var o = Object(this);
        var len = o.length >>> 0;
        if (typeof predicate !== 'function') {
          throw new TypeError('predicate must be a function');
        }
        var thisArg = arguments[1];
        var k = 0;
        while (k < len) {
          var kValue = o[k];
          if (predicate.call(thisArg, kValue, k, o)) {
            return kValue;
          }
          k++;
        }
        return undefined;
      }
    });
  }

  window.$app = i;

})(window);
